
/**
 * play(),
 * pause(),
 * destroy(),
 * setSize({width, height})
 */
(function (){
    var $ = jQuery;
    window.VideoEffect = function(obj){
        this.initialize.apply(this, arguments);
    };

    VideoEffect.prototype = {
        __options:{
            container:  null, // canvas parentNode
            mute:   true,
            mp4:    '', // 视频地址
            fps:    20, // 帧率
            width:  500, // 可见尺寸宽度 不包括alpha
            height: 500, // 可见尺寸高度
            preload:false,  // 预加载
            auto:   false,  // 初始化后自动播放
            endBack:function(){} // 播放完毕回调
        },
        initialize: function(options){
            var options = this.options = jQuery.extend(true, this.__options, options );
            console.log(options);
            this.canvas =$('<canvas></canvas>').appendTo(this.options.container)[0];
            this.canvas.width = this.options.width;
            this.canvas.height = this.options.height;
            this.gl = this.canvas.getContext('webgl');

            this._tick = $.proxy(this.__tick, this);
            this.interval = 1000/ options.fps;
            this.then = (new Date).getTime();

            this.radio = window.devicePixelRatio||1;
            this.gl = this.gl;
            this.initWebgl();
        },
        __tick: function(){
         this.timer = window.requestAnimationFrame(this._tick);
          now = (new Date).getTime();
          delta = now - this.then;
          if (delta > this.interval) {
           	this.then = now - (delta % this.interval);
            this.drawWebglFrame();
          }
        },
        destroy: function(){
            window.cancelAnimationFrame(this.timer);
            this.video.pause();
            this.cleanWebGL(this.gl);
            this.gl = null;
            window.URL.revokeObjectURL(this.video.src);
            this.video = null;
            this.canvas.remove();
        },
        play: function(){
            console.log(this.video);
            if(this.video){
                this.video.play();
            }else{
                var _player =  this,
                    // 兼容mp4全路径
                    _videoSrc = this.options.mp4;
                // 先缓存
                // this.options.preload = true;
                if(this.options.preload){
                    this.getVideoSurce( _videoSrc, function(blobSrc){
                        _player.show(blobSrc)
                    })
                }else{
                    _player.show(_videoSrc);
                }
            }
        },
        pause: function(){
            this.video.pause();
            cancelAnimationFrame(this.timer);
        },
        setSize:function(size){
            if(size){
                this.canvas.width=size.width;
                this.canvas.height=size.height;
                this.video.width = size.width /2;
                this.video.height = size.height;
                this.options.width = size.width;
                this.options.height = size.height;
                this.gl.viewport(
                    0,
                    0,
                    this.options.width * this.radio,
                    this.options.height * this.radio
                );
            }
        },
        tt:0,
        show: function(videoSrc){
                var _video = document.createElement('video');
                _video.crossOrigin='anonymous';
                _video.setAttribute('x-webkit-airplay', '');
                _video.setAttribute('webkit-playsinline', '');
                _video.setAttribute('playsinline', '');
                _video.width = this.options.width/2;
                _video.height = this.options.height;
                _video.style.display='none';
                document.body.appendChild(_video);

                _video.preload = 'auto';
                _video.mute = true;
                _video.volume = 0;
                _video.loop = this.options.loop;
                var _videoEffect = this;
                _video.addEventListener('play', function(){
                    cancelAnimationFrame(_videoEffect.timer)
                    _videoEffect._tick();
                }, false);

                _video.addEventListener('ended', function(){
                    // _videoEffect.destory();
                    if(!_videoEffect.options.loop){
                        _videoEffect.pause();
                    }
                    _videoEffect.options.endBack();
                }, false);
                _video.src = videoSrc;
                if(this.options.auto){
                    _video.play();
                }
                /* 
                var _promise = _video.play();
                if( _promise != undefined && _promise !=null && _promise.then){
                    _promise.then(function(){})
                            ['catch'](function(){
                                if(_video){
                                    _video.muted = true;
                                    _video.play();
                                }
                            });
                }else{
                    _video.muted = true;
                    _video.play();
                }; */
                this.video = _video;
        },

        
        getVideoSurce: function (source, callback){
            var URL = window.webkitURL || window.URL;
            var xhr = new XMLHttpRequest();
            xhr.open("GET", source, true);
            xhr.responseType = "blob";
            xhr.onload = function () {
                var _videoSrc;
                if (xhr.status === 200 || xhr.status === 304) {
                    _videoSrc = URL.createObjectURL(xhr.response);
                } else {
                    _videoSrc = false;
                }
                callback(_videoSrc);
            }
            xhr.send();
        },

        //webgl
        buffers:[],
        textures:[],
        shaders:[],
        program:false,
        cleanWebGL:function(gl){
            try{
                this.buffers.forEach(function(buffer){
                    gl.deleteBuffer(buffer);
                });
                delete this.buffers;
                this.textures.forEach(function(texture){
                    gl.deleteTexture(texture);
                });
                delete this.textures;
                this.shaders.forEach(function(shader){
                    gl.deleteShader(shader);
                });
                delete this.shaders;
                if(this.program){
                    gl.deleteProgram( this.program);
                }
                delete this.program;
            }catch(e){}
        },
        drawWebglFrame: function() {
            if(!this.video) return;
            var  gl = this.gl;
            // 配置纹理图像
            gl.texImage2D(
                gl.TEXTURE_2D,
                0,
                gl.RGBA,
                gl.RGBA,
                gl.UNSIGNED_BYTE,
                this.video
            );
            // 绘制
            gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
        },
        initWebgl: function() {
           /*  this.canvas = this.options.canvas;
            this.canvas.width = this.options.width * this.radio;
            this.canvas.height = this.options.height * this.radio;
            this.canvas.addEventListener('click', () => {
                this.play();
            });
            if (!this.canvas) {
                this.canvas = document.createElement('canvas');
                document.body.appendChild(this.canvas);
            }
    
            const gl = this.canvas.getContext('webgl'); */
            var gl = this.gl;
            // 后加
            gl.enable(gl.BLEND);
            gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
            
            gl.viewport(
                0,
                0,
                this.options.width * this.radio,
                this.options.height * this.radio
            );
    
            var  program = this.program =  this._initShaderProgram(gl);
            gl.linkProgram(program);
            gl.useProgram(program);
    
            this._initBuffer(gl);
    
            
    
            // 绑定纹理
            var texture = this._initTexture(gl);
            gl.bindTexture(gl.TEXTURE_2D, texture);
    
            var scaleLocation = gl.getUniformLocation(program, 'u_scale');
            gl.uniform2fv(scaleLocation, [this.radio, this.radio]);
            this.gl = gl;
            this.textures.push(texture);
        },
    
        _createShader: function(gl, type, source) {
            const shader = gl.createShader(type);
            gl.shaderSource(shader, source);
            gl.compileShader(shader);
            /*
            if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
                console.error(gl.getShaderInfoLog(shader));
            } */
    
            return shader;
        },
    
        _initShaderProgram: function(gl) {
            // 顶点着色器glsl代码
            const vsSource = `
            attribute vec2 a_position;
            attribute vec2 a_texCoord;
            varying vec2 v_texCoord;
            uniform vec2 u_scale;
            void main(void) {
                gl_Position = vec4(a_position, 0.0, 1.0);
                v_texCoord = a_texCoord;
            }
            `;
            // 片元着色器 glsl 代码
            const fsSource = `
            precision lowp float;
            varying vec2 v_texCoord;
            uniform sampler2D u_sampler;
            void main(void) {
                gl_FragColor = vec4(texture2D(u_sampler, v_texCoord).rgb, texture2D(u_sampler, v_texCoord+vec2(-0.5, 0)).r);
            }
            `;
            const vsShader = this._createShader(gl, gl.VERTEX_SHADER, vsSource);
            const fsShader = this._createShader(gl, gl.FRAGMENT_SHADER, fsSource);
            const program = this.program = gl.createProgram();
            gl.attachShader(program, vsShader);
            gl.attachShader(program, fsShader);
            // gl.linkProgram(program);
            this.shaders.push(vsShader);
            this.shaders.push(fsShader);
            return program;
        },
        _initBuffer: function(gl) {
            var positionVertice = new Float32Array([
                -1.0, 1.0,  0.5, 1.0, 
                1.0, 1.0, 1.0, 1.0,
                -1.0, -1.0, 0.5, 0.0,
                1.0, -1.0, 1.0, 0.0
            ]);
            var positionBuffer = gl.createBuffer(); // 创建buffer
            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); // 把缓冲区对象绑定到目标
            gl.bufferData(gl.ARRAY_BUFFER, positionVertice, gl.STATIC_DRAW); // 向缓冲区对象写入刚定义的顶点数据
            
            var size = positionVertice.BYTES_PER_ELEMENT;

            var aPosition = gl.getAttribLocation(this.program, 'a_position');
            gl.enableVertexAttribArray(aPosition);
            var aTexCoord = gl.getAttribLocation(this.program, 'a_texCoord');
            gl.enableVertexAttribArray(aTexCoord);
            
            gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, size*4 , 0);
            gl.vertexAttribPointer(aTexCoord, 2, gl.FLOAT, false, size*4, size*2);

            this.buffers.push(positionBuffer);

        },
    
        _initTexture: function(gl) {
            var texture = gl.createTexture();
    
            gl.bindTexture(gl.TEXTURE_2D, texture);
            // 对纹理图像进行y轴反转，因为WebGL纹理坐标系统的t轴（分为t轴和s轴）的方向和图片的坐标系统Y轴方向相反。因此将Y轴进行反转。
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
            // 配置纹理参数
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
            return texture;
        }
    }
})();